From 636eaa12d90b7151f454ec45dd47679292ece9ab Mon Sep 17 00:00:00 2001 From: Keir Fraser Date: Wed, 7 Oct 2009 07:47:50 +0100 Subject: [PATCH] Tools-side support for creating and destroying netchannel2 interfaces. Signed-off-by: Steven Smith --- tools/hotplug/Linux/Makefile | 1 + tools/hotplug/Linux/vif2 | 46 +++++++ tools/hotplug/Linux/xen-backend.rules | 5 +- tools/python/xen/xend/XendDevices.py | 3 +- tools/python/xen/xend/XendDomainInfo.py | 2 +- tools/python/xen/xend/server/netif2.py | 163 ++++++++++++++++++++++++ tools/python/xen/xm/create.py | 20 +++ tools/python/xen/xm/main.py | 44 +++++++ 8 files changed, 280 insertions(+), 4 deletions(-) create mode 100644 tools/hotplug/Linux/vif2 create mode 100644 tools/python/xen/xend/server/netif2.py diff --git a/tools/hotplug/Linux/Makefile b/tools/hotplug/Linux/Makefile index 33ebdc6487..b5f9800de0 100644 --- a/tools/hotplug/Linux/Makefile +++ b/tools/hotplug/Linux/Makefile @@ -11,6 +11,7 @@ XENDOMAINS_SYSCONFIG = init.d/sysconfig.xendomains XEN_SCRIPTS = network-bridge vif-bridge XEN_SCRIPTS += network-route vif-route XEN_SCRIPTS += network-nat vif-nat +XEN_SCRIPTS += vif2 XEN_SCRIPTS += block XEN_SCRIPTS += block-enbd block-nbd XEN_SCRIPTS += blktap diff --git a/tools/hotplug/Linux/vif2 b/tools/hotplug/Linux/vif2 new file mode 100644 index 0000000000..247fa67acf --- /dev/null +++ b/tools/hotplug/Linux/vif2 @@ -0,0 +1,46 @@ +#!/bin/bash + +dir=$(dirname "$0") +. "$dir/xen-hotplug-common.sh" +. "$dir/xen-network-common.sh" + +bridge=$(xenstore_read_default "$XENBUS_PATH/bridge" "$bridge") +if [ -z "$bridge" ] + then + nr_bridges=$(($(brctl show | cut -f 1 | grep -v "^$" | wc -l) - 1)) + if [ "$nr_bridges" != 1 ] + then + fatal "no bridge specified, and don't know which one to use ($nr_bridges found)" + fi + bridge=$(brctl show | cut -d " +" -f 2 | cut -f 1) +fi + +command="$1" +shift + +case "$command" in + "online") + if [ "$bridge" != "-" ] + then + setup_bridge_port "$vif" + add_to_bridge "$bridge" "$vif" + else + # Just let the normal udev rules for interfaces handle it. + true + fi + success + ;; + + "add") + success + ;; + + "remove") + ;; + + *) + echo "Unknown command: $command" + echo 'Valid commands are: add, remove, online' + exit 1 +esac diff --git a/tools/hotplug/Linux/xen-backend.rules b/tools/hotplug/Linux/xen-backend.rules index 3b1c1759da..60690b0833 100644 --- a/tools/hotplug/Linux/xen-backend.rules +++ b/tools/hotplug/Linux/xen-backend.rules @@ -1,8 +1,9 @@ SUBSYSTEM=="xen-backend", KERNEL=="tap*", RUN+="/etc/xen/scripts/blktap $env{ACTION}" SUBSYSTEM=="xen-backend", KERNEL=="vbd*", RUN+="/etc/xen/scripts/block $env{ACTION}" SUBSYSTEM=="xen-backend", KERNEL=="vtpm*", RUN+="/etc/xen/scripts/vtpm $env{ACTION}" -SUBSYSTEM=="xen-backend", KERNEL=="vif*", ACTION=="online", RUN+="$env{script} online" -SUBSYSTEM=="xen-backend", KERNEL=="vif*", ACTION=="offline", RUN+="$env{script} offline" +SUBSYSTEM=="xen-backend", KERNEL=="vif2-*", RUN+="/etc/xen/scripts/vif2 $env{ACTION}" +SUBSYSTEM=="xen-backend", KERNEL=="vif-*", ACTION=="online", RUN+="$env{script} online" +SUBSYSTEM=="xen-backend", KERNEL=="vif-*", ACTION=="offline", RUN+="$env{script} offline" SUBSYSTEM=="xen-backend", KERNEL=="vscsi*", RUN+="/etc/xen/scripts/vscsi $env{ACTION}" SUBSYSTEM=="xen-backend", ACTION=="remove", RUN+="/etc/xen/scripts/xen-hotplug-cleanup" KERNEL=="evtchn", NAME="xen/%k" diff --git a/tools/python/xen/xend/XendDevices.py b/tools/python/xen/xend/XendDevices.py index b214891432..5cd3b65d0b 100644 --- a/tools/python/xen/xend/XendDevices.py +++ b/tools/python/xen/xend/XendDevices.py @@ -19,7 +19,7 @@ # A collection of DevControllers # -from xen.xend.server import blkif, netif, tpmif, pciif, iopif, irqif, vfbif, vscsiif +from xen.xend.server import blkif, netif, tpmif, pciif, iopif, irqif, vfbif, vscsiif, netif2 from xen.xend.server.BlktapController import BlktapController, Blktap2Controller from xen.xend.server.ConsoleController import ConsoleController @@ -37,6 +37,7 @@ class XendDevices: controllers = { 'vbd': blkif.BlkifController, 'vif': netif.NetifController, + 'vif2': netif2.NetifController2, 'vtpm': tpmif.TPMifController, 'pci': pciif.PciController, 'ioports': iopif.IOPortsController, diff --git a/tools/python/xen/xend/XendDomainInfo.py b/tools/python/xen/xend/XendDomainInfo.py index 6848d3b3ee..e9dfa15782 100644 --- a/tools/python/xen/xend/XendDomainInfo.py +++ b/tools/python/xen/xend/XendDomainInfo.py @@ -1222,7 +1222,7 @@ class XendDomainInfo: break self._waitForDevice_destroy(deviceClass, devid, backend) - if rm_cfg: + if rm_cfg and deviceClass != "vif2": if deviceClass == 'vif': if self.domid is not None: mac = '' diff --git a/tools/python/xen/xend/server/netif2.py b/tools/python/xen/xend/server/netif2.py new file mode 100644 index 0000000000..a098c13b5c --- /dev/null +++ b/tools/python/xen/xend/server/netif2.py @@ -0,0 +1,163 @@ +#============================================================================ +# This library is free software; you can redistribute it and/or +# modify it under the terms of version 2.1 of the GNU Lesser General Public +# License as published by the Free Software Foundation. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +#============================================================================ +# Copyright (C) 2004, 2005 Mike Wray +# Copyright (C) 2005 XenSource Ltd +# Copyright (C) 2008 Citrix Systems Inc. +#============================================================================ +# +# Based closely on netif.py. +# + +"""Support for virtual network interfaces, version 2. +""" + +import os +import random +import re +import time + +from xen.xend import XendOptions +from xen.xend.server.DevController import DevController +from xen.xend.XendError import VmError +from xen.xend.XendXSPolicyAdmin import XSPolicyAdminInstance +from xen.xend.xenstore.xstransact import xstransact +import xen.util.xsm.xsm as security + +from xen.xend.XendLogging import log + +xoptions = XendOptions.instance() + +def randomMAC(): + """Generate a random MAC address. + + Uses OUI (Organizationally Unique Identifier) 00-16-3E, allocated to + Xensource, Inc. The OUI list is available at + http://standards.ieee.org/regauth/oui/oui.txt. + + The remaining 3 fields are random, with the first bit of the first + random field set 0. + + @return: MAC address string + """ + mac = [ 0x00, 0x16, 0x3e, + random.randint(0x00, 0x7f), + random.randint(0x00, 0xff), + random.randint(0x00, 0xff) ] + return ':'.join(map(lambda x: "%02x" % x, mac)) + +class NetifController2(DevController): + def __init__(self, vm): + DevController.__init__(self, vm) + + def getDeviceDetails(self, config): + """@see DevController.getDeviceDetails""" + + devid = self.allocateDeviceID() + + bridge = config.get('bridge') + back_mac = config.get('back_mac') + if not back_mac: + if bridge: + back_mac = "fe:ff:ff:ff:ff:ff" + else: + back_mac = randomMAC() + front_mac = config.get('front_mac') or randomMAC() + front_trust = config.get("trusted") or "0" + back_trust = config.get("back_trusted") or "1" + max_bypasses = config.get("max_bypasses") or "5" + pdev = config.get('pdev') + front_filter = config.get("front_filter_mac") + if front_filter == None: + if back_trust == "0": + front_filter = "1" + else: + front_filter = "0" + back_filter = config.get("filter_mac") + if back_filter == None: + if front_trust == "0": + back_filter = "1" + else: + back_filter = "0" + back = { 'mac': back_mac, 'remote-mac': front_mac, + 'handle': "%i" % devid, 'local-trusted': back_trust, + 'remote-trusted': front_trust, 'filter-mac': back_filter, + 'max-bypasses': max_bypasses } + + front = { 'mac': front_mac, 'remote-mac': back_mac, + 'local-trusted': front_trust, 'remote-trusted': back_trust, + 'filter-mac': front_filter } + + if bridge: + back['bridge'] = bridge + + if pdev: + back['pdev'] = pdev + + return (devid, back, front) + + def getDeviceConfiguration(self, devid, transaction = None): + """@see DevController.configuration""" + + if transaction is None: + read_fn = xstransact.Read + else: + read_fn = transaction.read + def front_read(x): + return read_fn(frontpath + x) + def back_read(x): + return read_fn(backpath + x) + + result = DevController.getDeviceConfiguration(self, devid, transaction) + + dev = self.convertToDeviceNumber(devid) + frontpath = self.frontendPath(dev) + "/" + + backpath = front_read("backend") + "/" + + front_mac = front_read("mac") + back_mac = back_read("mac") + + front_trusted = back_read("remote-trusted") + back_trusted = back_read("local-trusted") + max_bypasses = back_read("max-bypasses") + + bridge = back_read("bridge") + + pdev = back_read("pdev") + + if front_mac: + result["front_mac"] = front_mac + if back_mac: + result["back_mac"] = back_mac + if front_trusted: + result["front_trusted"] = front_trusted + if back_trusted: + result["back_trusted"] = back_trusted + if bridge: + result["bridge"] = bridge + if pdev: + result["pdev"] = pdev + if max_bypasses: + result["max-bypasses"] = max_bypasses + return result + + def destroyDevice(self, devid, force): + dev = self.convertToDeviceNumber(devid) + self.writeBackend(dev, "online", "0") + if force: + self.writeBackend(dev, "shutdown-request", "force") + else: + self.writeBackend(dev, "shutdown-request", "normal") + self.vm._removeVm("device/%s/%d" % (self.deviceClass, dev)) diff --git a/tools/python/xen/xm/create.py b/tools/python/xen/xm/create.py index 14f8aa6425..f929011bc7 100644 --- a/tools/python/xen/xm/create.py +++ b/tools/python/xen/xm/create.py @@ -393,6 +393,12 @@ gopts.var('vif', val="type=TYPE,mac=MAC,bridge=BRIDGE,ip=IPADDR,script=SCRIPT," This option may be repeated to add more than one vif. Specifying vifs will increase the number of interfaces as needed.""") +gopts.var('vif2', val="front_mac=MAC,back_mac=MAC,backend=DOM,pdev=PDEV,max_bypasses=N,bridge=BRIDGE,filter_mac=<0|1>,front_filter_mac=<0|1>", + fn=append_value, default=[], + use="""Add a netchannel2 network interface using given front + and backend MAC addresses. Randomly generated + addresses will be used if either address is missing.""") + gopts.var('vtpm', val="instance=INSTANCE,backend=DOM,type=TYPE", fn=append_value, default=[], use="""Add a TPM interface. On the backend side use the given @@ -931,6 +937,8 @@ def configure_vifs(config_devs, vals): vifs = vals.vif vifs_n = len(vifs) + vifs2 = vals.vif2 + vifs2_n = len(vifs2) if hasattr(vals, 'nics'): if vals.nics > 0: @@ -957,6 +965,18 @@ def configure_vifs(config_devs, vals): map(f, d.keys()) config_devs.append(['device', config_vif]) + for c in vifs2: + d = comma_sep_kv_to_dict(c) + config_vif = ['vif2'] + + for k in d.keys(): + if k not in ['front_mac', 'back_mac', 'backend', 'trusted', + 'back_trusted', 'front_filter_mac', 'filter_mac', + 'bridge', 'pdev', 'max_bypasses' ]: + err('Invalid vif2 option: ' + k) + config_vif.append([k, d[k]]) + config_devs.append(['device', config_vif]) + def configure_hvm(config_image, vals): """Create the config for HVM devices. diff --git a/tools/python/xen/xm/main.py b/tools/python/xen/xm/main.py index 6ffa0ed1bf..07f77bf29e 100644 --- a/tools/python/xen/xm/main.py +++ b/tools/python/xen/xm/main.py @@ -181,6 +181,15 @@ SUBCOMMAND_HELP = { 'Destroy a domain\'s virtual network device.'), 'network-list' : (' [--long]', 'List virtual network interfaces for a domain.'), + 'network2-attach': (' [front_mac=] [back_mac=] ' + '[backend=] [trusted=<0|1>] ' + '[back_trusted=<0|1>] [bridge=] ' + '[max_bypasses=n]' + 'Create a new version 2 virtual network device.'), + 'network2-detach': (' [-f|--force]', + 'Destroy a domain\'s version 2 virtual network device.'), + 'network2-list' : (' [--long]', + 'List version 2 virtual network interfaces for a domain.'), 'vnet-create' : ('','Create a vnet from ConfigFile.'), 'vnet-delete' : ('', 'Delete a Vnet.'), 'vnet-list' : ('[-l|--long]', 'List Vnets.'), @@ -399,6 +408,9 @@ device_commands = [ "network-attach", "network-detach", "network-list", + "network2-attach", + "network2-detach", + "network2-list", "vtpm-list", "pci-attach", "pci-detach", @@ -2436,6 +2448,35 @@ def xm_block_configure(args): server.xend.domain.device_configure(dom, vbd) +def xm_network2_attach(args): + xenapi_unsupported() + arg_check(args, 'network2-attach', 1, 4) + dom = args[0] + vif = ['vif2'] + vif_params = ['front_mac', 'back_mac', 'backend', 'trusted', + 'back_trusted', "front_filter_mac", "filter_mac", + 'bridge', 'pdev', "max_bypasses" ] + for a in args[1:]: + vif_param = a.split("=") + if len(vif_param) != 2 or vif_param[1] == "" or \ + vif_param[0] not in vif_params: + err("Invalid argument: %s" % a) + usage("network2-attach") + vif.append(vif_param) + server.xend.domain.device_create(dom, vif) + +def xm_network2_detach(args): + xenapi_unsupported() + arg_check(args, "network2-detch", 2, 3) + detach(args, "vif2") + +def xm_network2_list(args): + xenapi_unsupported() + (use_long, params) = arg_check_for_resource_list(args, "network2-list") + dom = params[0] + devs = server.xend.domain.getDeviceSxprs(dom, 'vif2') + map(PrettyPrint.prettyprint, devs) + def xm_network_attach(args): arg_check(args, 'network-attach', 1, 11) @@ -3239,6 +3280,9 @@ commands = { "network-attach": xm_network_attach, "network-detach": xm_network_detach, "network-list": xm_network_list, + "network2-attach": xm_network2_attach, + "network2-detach": xm_network2_detach, + "network2-list": xm_network2_list, # network (as in XenAPI) "network-new": xm_network_new, "network-del": xm_network_del, -- 2.30.2